from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema
from rest_framework.response import Response
from rest_framework.viewsets import GenericViewSet
from utils.MyResponse import SuccessResponse, ErrorResponse
from utils.validator import CustomValidationError


def get_object_or_error(queryset, *args, **kwargs):
    try:
        return queryset.get(*args, **kwargs)
    except queryset.model.DoesNotExist:
        raise CustomValidationError(detail='未找到数据', code='manually')


class CustomView(GenericViewSet):

    user_filter_fields = None

    def get_object(self):
        queryset = self.filter_queryset(self.get_queryset())

        # Perform the lookup filtering.
        lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field

        # key值不在传入的参数，代码写错 url匹配值和类lookup_field值不一致
        assert lookup_url_kwarg in self.kwargs, (
            'Expected view %s to be called with a URL keyword argument '
            'named "%s". Fix your URL conf, or set the `.lookup_field` '
            'attribute on the view correctly.' %
            (self.__class__.__name__, lookup_url_kwarg)
        )
        filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
        obj = get_object_or_error(queryset, **filter_kwargs)

        # May raise a permission denied
        self.check_object_permissions(self.request, obj)

        return obj

    def create_user_data(self, request, *args, **kwargs):
        """
        创建一条用户数据
        """
        serializer_class = self.get_serializer_class()
        request.data['user'] = request.user.id
        serializer = serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)

        serializer.save()
        return SuccessResponse(serializer.data)

    def create(self, request, *args, **kwargs):
        """
        创建一条数据
        """

        serializer_class = self.get_serializer_class()
        serializer = serializer_class(data=request.data, request=request)
        serializer.is_valid(raise_exception=True)

        serializer.save()
        return SuccessResponse(serializer.data)

    def perform_update(self, serializer):
        """
        执行更新
        """
        serializer.save()

    def update(self, request, *args, **kwargs):
        """
        更新数据


        更新一条数据的全部字段
        """
        partial = kwargs.pop('partial', False)
        instance = self.get_object()

        serializer_class = self.get_serializer_class()
        serializer = serializer_class(instance, data=request.data, partial=partial, request=request)
        # serializer = self.get_serializer(instance, data=request.data, partial=partial, request=request)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)
        return SuccessResponse(serializer.data)

    def partial_update(self, request, *args, **kwargs):
        """
        更新一条数据


        更新一条数据的部分字段
        """
        kwargs['partial'] = True
        return self.update(request, *args, **kwargs)

    def destroy(self, request, *args, **kwargs):
        """
        删除数据


        删除数据
        """
        instance = self.get_object()
        instance.delete()
        return SuccessResponse(data=[], msg="删除成功")

    keys = openapi.Schema(description='主键列表', type=openapi.TYPE_ARRAY, items=openapi.Schema(type=openapi.TYPE_INTEGER))

    @swagger_auto_schema(request_body=openapi.Schema(
        type=openapi.TYPE_OBJECT,
        required=['keys'],
        properties={'keys': keys}
    ))
    def multiple_destroy(self, request, *args, **kwargs):
        """
        删除数据


        删除数据，传入的是数组，表示可以删除多条
        """
        queryset = self.filter_queryset(self.get_queryset())
        if self.user_filter_fields:
            filter_dict = dict()
            filter_dict[self.user_filter_fields] = request.user.id
            queryset = queryset.filter(**filter_dict)
        queryset = queryset.filter(id__in=request.data.get('keys', []))
        if queryset.exists():
            queryset.delete()
            return SuccessResponse(None, msg='删除成功')
        else:
            return ErrorResponse(None, msg='未找到数据')

    def list(self, request, *args, **kwargs):
        """
        查询数据
        """

        queryset = self.filter_queryset(self.get_queryset())
        if self.user_filter_fields:
            filter_dict = dict()
            filter_dict[self.user_filter_fields] = request.user.id
            queryset = queryset.filter(**filter_dict)
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        serializer = self.get_serializer(queryset, many=True)
        return SuccessResponse(data=serializer.data, msg="获取成功")

    def retrieve(self, request, *args, **kwargs):
        """
        查询单条数据
        """
        instance = self.get_object()
        serializer = self.get_serializer(instance)
        return Response(serializer.data)


class MixinGetList:
    """
    get获取数据
    """

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)


class MixinPostCreateModel:
    """
    post增加数据
    """
    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)


class MixinPutUpdateModel:
    """
    put修改数据,可以修改部分
    """
    def put(self, request, *args, **kwargs):
        return self.partial_update(request, *args, **kwargs)


class MixinPutAllUpdateModel:
    """
    put修改数据,去修改所有字段
    """
    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)


class MixinDeleteDestroyModel:
    """
    delete删除一条数据
    """
    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)


class MixinMultipleDeleteDestroyModel:
    """
    delete批量删除数据
    """

    def delete(self, request, *args, **kwargs):
        return self.multiple_destroy(request, *args, **kwargs)


class CustomModelViewSet(CustomView, MixinGetList, MixinPostCreateModel, MixinPutUpdateModel, MixinMultipleDeleteDestroyModel):
    """
    增删改查
    """
    pass

